<?php
/**
 * Automatically loads classes that are not already included
 * Looks for classes in every current site's Lib/, Model/ and Modules/* directories
 */
class AutoLoader {
	/**
	 * Loads the requested $class if it exists
	 *
	 * @param string $class
	 */
	public static function load ($class) {
		# We need to know which sites are currently requested
		$sites = SleekPHP::site()->getSites();

		# If class name contains '_' it is considered a module
		if (strpos($class, '_') !== false) {
			if (!self::loadModuleClass($class, $sites)) {
				throw new Exception("The module class \"$class\" could not be found in its site.");
			}

			Logger::log("The module class \"$class\" has been loaded.", __METHOD__);
		}
		# Not a module class, check if it's a lib or model-class
		else {
			if (!self::loadLibClass($class, $sites)) {
				if (!self::loadModelClass($class, $sites)) {
					throw new Exception("The class \"$class\" could not be found in any of your site's Lib/ or Model/ directories.");
				}
			}

			Logger::log("The class \"$class\" has been loaded.", __METHOD__);
		}
	}

	/**
	 * Loads the requested $class from any $sites Modules/ dir
	 *
	 * @param string $class
	 * @param array $sites
	 */
	private static function loadModuleClass ($class, array $sites) {
		$classPortions	= explode('_', $class);
		$site			= $classPortions[0];
		$module			= substr($classPortions[1], 0, -6); # Minus "Module"
		$path			= DOCROOT . "Sites/$site/Modules/$module/{$module}Module.php";

		# Make sure requested class exists in one of the current sites
		if (!in_array($site, $sites)) {
			throw new Exception("Requested class \"$class\" belongs to a site outside the current sites \"" . implode(', ', SleekPHP::site()->getSites()) . "\".<br/>Not sure how that happened but something's gone pretty wrong. You can try extending the site this class belongs to ($site) from your site's .info file.");
		}

		# Make sure path exists
		if (file_exists($path)) {
			include $path;

			return true;
		}
		# Class not found
		else {
			return false;
		}
	}

	/**
	 * Loads the requested $class from any $sites Lib/ dir
	 *
	 * @param string $class
	 * @param array $sites
	 */
	private static function loadLibClass ($class, array $sites) {
		return self::loadAnyClass($class, $sites, 'Lib');
	}

	/**
	 * Loads the requested $class from any $sites Model/ dir
	 *
	 * @param string $class
	 * @param array $sites
	 */
	private static function loadModelClass ($class, array $sites) {
		return self::loadAnyClass($class, $sites, 'Models');
	}

	/**
	 * Loads the requested $class from any $sites $dir
	 *
	 * @param string $class
	 * @param array $sites
	 * @param string $dir
	 */
	private static function loadAnyClass ($class, array $sites, $dir) {
		foreach ($sites as $site) {
			$path = DOCROOT . "Sites/$site/$dir/$class.php";

			if (file_exists($path)) {
				include $path;

				return true;
			}
		}

		return false;
	}
}
